package cn.topcodes.tcsf.admin.commons.api.controller.generic;

import cn.topcode.unicorn.utils.ValidationUtil;
import cn.topcodes.tcsf.admin.commons.api.controller.query.QueryIdEntityApiController;
import cn.topcodes.tcsf.admin.commons.api.domain.ApiResponseEntity;
import cn.topcodes.tcsf.admin.commons.convertor.Form2EntityConvertor;
import cn.topcodes.tcsf.admin.commons.domain.IdEntity;
import cn.topcodes.tcsf.admin.commons.domain.Idable;
import cn.topcodes.tcsf.admin.commons.generic.IGenericService;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public abstract class GenericApiController<T extends IdEntity, V, F extends Idable>
        extends QueryIdEntityApiController<T, V> implements GenericApi<F, V> {

    @Autowired
    private IGenericService<T> genericService;

    @Autowired(required = false)
    private Form2EntityConvertor<T,F> form2EntityConvertor;

    @Override
    public ApiResponseEntity<Void> delete(
            @ApiParam(value = "资源ID") @RequestParam(required = true) Long id) {
        this.genericService.delete(id);
        return ApiResponseEntity.buildOK();
    }

    /*慎重删除*/
    @Override
    @ResponseBody
    @RequestMapping(value = "careful-delete",method = RequestMethod.POST)
    public ApiResponseEntity carefulDelete(
            @RequestParam Long id,
            @RequestParam String password
    ) {
        boolean isPwdEqual = validateOperation(password);
        if(isPwdEqual) {
            this.getService().delete(id);
            return ApiResponseEntity.buildOK();
        }else {
            return ApiResponseEntity.buildFailed("密码错误");
        }
    }

    protected boolean validateOperation(String password) {
        throw new IllegalArgumentException("不支持慎重删除操作");
    }

    @Override
    public ApiResponseEntity<Void> batchDelete(
            @ApiParam(value = "资源ID数组") @RequestParam(required = true,name = "ids[]") Long[] ids) {
        this.genericService.batchDelete(ids);
        return ApiResponseEntity.buildOK();
    }

    @Override
    public ApiResponseEntity<Void> markDelete(
            @ApiParam(value = "资源ID") @RequestParam(required = true) Long id) {
        this.genericService.markDelete(id);
        return ApiResponseEntity.buildOK();
    }

    @Override
    public ApiResponseEntity<Void> batchMarkDelete(
            @ApiParam(value = "资源ID数组") @RequestParam(required = true,name = "ids[]") Long[] ids) {
        this.genericService.batchMarkDelete(ids);
        return ApiResponseEntity.buildOK();
    }

    @Override
    public ApiResponseEntity<Void> disable(
            @ApiParam(value = "资源ID") @RequestParam(required = true) Long id) {
        this.genericService.disable(id);
        return ApiResponseEntity.buildOK();
    }

    @Override
    public ApiResponseEntity<Void> batchDisable(
            @ApiParam(value = "资源ID数组") @RequestParam(required = true,name = "ids[]") Long[] ids) {
        this.genericService.batchDisable(ids);
        return ApiResponseEntity.buildOK();
    }

    @Override
    public ApiResponseEntity<Void> enable(
            @ApiParam(value = "资源ID") @RequestParam(required = true) Long id) {
        this.genericService.enable(id);
        return ApiResponseEntity.buildOK();
    }

    @Override
    public ApiResponseEntity<Void> batchEnable(
            @ApiParam(value = "资源ID数组") @RequestParam(required = true,name = "ids[]") Long[] ids) {
        this.genericService.batchEnable(ids);
        return ApiResponseEntity.buildOK();
    }

    @Override
    public ApiResponseEntity create(
            HttpServletRequest request,
            @Valid @ApiParam(value = "创建资源表单") F form,
            BindingResult result) {
        ValidationUtil.validate(result);
        T entity = this.form2Entity(form);
        Long id = this.genericService.create(entity);
        return ApiResponseEntity.buildOK().setBody(id);
    }

    @Override
    public ApiResponseEntity<Void> batchCreate(
            HttpServletRequest request,
            @Valid @ApiParam(value = "批量创建资源表单数组") F[] forms,
            BindingResult result) {
        ValidationUtil.validate(result);
        List<T> list = this.form2Entity(forms);
        this.genericService.batchCreate(list);
        return ApiResponseEntity.buildOK();
    }

    @Override
    public ApiResponseEntity<Void> update(
            HttpServletRequest request,
            @Valid @ApiParam(value = "更新资源表单") F form,
            BindingResult result) {
        ValidationUtil.validate(result);
        T t = this.form2Entity(form);
        this.genericService.update(t);
        return ApiResponseEntity.buildOK();
    }

    @Override
    public ApiResponseEntity<Void> batchUpdate(
            HttpServletRequest request,
            @Valid @ApiParam(value = "批量更新资源表单数组") F[] forms,
            BindingResult result) {
        ValidationUtil.validate(result);
        List<T> list = this.form2Entity(forms);
        this.genericService.batchUpdate(list);
        return ApiResponseEntity.buildOK();
    }

    protected List<T> form2Entity(F[] forms) {
        Assert.notNull(forms);
        Class<T> entityClass = this.genericService.getEntityClass();
        if(this.getFormClass().equals(entityClass)) {
            return (List<T>) Arrays.asList(forms);
        }
        if(this.form2EntityConvertor != null) {
            List<F> formList = Arrays.asList(forms);
            return this.form2EntityConvertor.convertList(formList);
        }else {
            List<T> list = new ArrayList<T>();
            for (F f : forms) {
                T t = this.form2Entity(f);
                list.add(t);
            }
            return list;
        }
    }

    protected T form2Entity(F form) {
        Assert.notNull(form);
        Class<T> entityClass = this.genericService.getEntityClass();
        if(this.getFormClass().equals(entityClass)) {
            return (T) form;
        }
        if(this.form2EntityConvertor != null) {
            return this.form2EntityConvertor.convert(form);
        }else {
            try {
                T entity = this.genericService.getEntityClass().newInstance();
                BeanUtils.copyProperties(form, entity);
                form2EntityDiff(form,entity);
                return entity;
            } catch (Exception e) {
                throw new IllegalStateException("实体类型定义有误", e);
            }
        }
    }

    protected void form2EntityDiff(F form, T entity) {

    }

    @SuppressWarnings("unchecked")
    public Class<F> getFormClass() {
        Class<F> entityClass = (Class<F>) ((ParameterizedType) getClass().getGenericSuperclass())
                .getActualTypeArguments()[2];
        return entityClass;
    }

    protected IGenericService<T> getService() {
        return this.genericService;
    }
}
